package parser

import (
	"fmt"
	"monkey/ast"
	"monkey/lexer"
	"monkey/token"
	"strconv"
)

const (
	// 占位
	_ int = iota
	// LOWEST 最低的优先级
	LOWEST
	// EQUALS =，!=
	EQUALS
	// LESSGREATER <，>
	LESSGREATER
	// SUM +，-
	SUM
	// PRODUCT *，/
	PRODUCT
	// PREFIX !，-
	PREFIX
	// CALL (，函数调用
	CALL
	INDEX
)

// 定义所有的token类型对应的整数值
var precedences = map[token.TokenType]int{
	token.EQ:       EQUALS,
	token.NOT_EQ:   EQUALS,
	token.LT:       LESSGREATER,
	token.GT:       LESSGREATER,
	token.PLUS:     SUM,
	token.MINUS:    SUM,
	token.SLASH:    PRODUCT,
	token.ASTERISK: PRODUCT,
	token.LPAREN:   CALL,
	token.LBRACKET: INDEX,
}

type (
	// 解析前缀表达式
	prefixParseFn func() ast.Expression
	// 解析中缀表达式
	infixParseFn func(ast.Expression) ast.Expression
)

type Parser struct {
	// Lexer指针
	l *lexer.Lexer
	// 错误信息
	errors []string

	// 当前指针指向的token
	currToken token.Token
	// 指针指向的下一个token
	peekToken token.Token

	// 前缀解析函数map
	prefixParseFns map[token.TokenType]prefixParseFn
	// 中缀解析函数map
	infixParseFns map[token.TokenType]infixParseFn
}

// New 实例化Parser
func New(l *lexer.Lexer) *Parser {
	p := &Parser{
		l:      l,
		errors: []string{},
	}

	p.prefixParseFns = make(map[token.TokenType]prefixParseFn)
	// 注册标识符的前缀表达式的解析函数
	p.registerPrefix(token.IDENT, p.parseIdentifier)
	// 注册整数的前缀表达式的解析函数
	p.registerPrefix(token.INT, p.parseIntegerLiteral)
	// 注册字符串前缀表达式的解析函数
	p.registerPrefix(token.STRING, p.parseStringLiteral)
	// 注册!的前缀表达式的解析函数
	p.registerPrefix(token.BANG, p.parsePrefixExpression)
	// 注册-的前缀表达式的解析函数
	p.registerPrefix(token.MINUS, p.parsePrefixExpression)
	// 注册true的前缀表达式的解析函数
	p.registerPrefix(token.TRUE, p.parseBoolean)
	// 注册false的前缀表达式的解析函数
	p.registerPrefix(token.FALSE, p.parseBoolean)
	// 注册(的前缀表达式的解析函数
	p.registerPrefix(token.LPAREN, p.parseGroupedExpression)
	// 注册if的前缀表达式的解析函数
	p.registerPrefix(token.IF, p.parseIfExpression)
	// 注册函数的前缀表达式的解析函数
	p.registerPrefix(token.FUNCTION, p.parseFunctionLiteral)
	p.registerPrefix(token.LBRACKET, p.parseArrayLiteral)
	p.registerPrefix(token.LBRACE, p.parseHashLiteral)

	p.infixParseFns = make(map[token.TokenType]infixParseFn)
	// 注册+的中缀表达式的解析函数
	p.registerInfix(token.PLUS, p.parseInfixExpression)
	// 注册-的中缀表达式的解析函数
	p.registerInfix(token.MINUS, p.parseInfixExpression)
	// 注册/的中缀表达式的解析函数
	p.registerInfix(token.SLASH, p.parseInfixExpression)
	// 注册*的中缀表达式的解析函数
	p.registerInfix(token.ASTERISK, p.parseInfixExpression)
	// 注册=的中缀表达式的解析函数
	p.registerInfix(token.EQ, p.parseInfixExpression)
	// 注册!=的中缀表达式的解析函数
	p.registerInfix(token.NOT_EQ, p.parseInfixExpression)
	// 注册<的中缀表达式的解析函数
	p.registerInfix(token.LT, p.parseInfixExpression)
	// 注册>的中缀表达式的解析函数
	p.registerInfix(token.GT, p.parseInfixExpression)

	// 注册(的中缀表达式的解析函数
	p.registerInfix(token.LPAREN, p.parseCallExpression)
	p.registerInfix(token.LBRACKET, p.parseIndexExpression)

	// 这里调用了2次nextToken，第一次currToken = nil，peekToken = 第一个token，
	// 第二次，currToken = 第一个token，peekToken = 第二个token
	p.nextToken()
	p.nextToken()

	return p
}

// 获取下一个token，currToken指向下一个token，peekToken指向下两个token
func (p *Parser) nextToken() {
	p.currToken = p.peekToken
	p.peekToken = p.l.NextToken()
}

// 辅助函数，判断当前token的类型与给出的token的类型是否相等
func (p *Parser) currTokenIs(t token.TokenType) bool {
	return t == p.currToken.Type
}

// 辅助函数，判断下一个token的类型与给出的token的类型是否相等
func (p *Parser) peekTokenIs(t token.TokenType) bool {
	return t == p.peekToken.Type
}

// 判断下一个token与给出的token的类型是否相等，相等的话，前移指针，当前指针指向下一个token
func (p *Parser) expectPeek(t token.TokenType) bool {
	if p.peekTokenIs(t) {
		p.nextToken()
		return true
	}
	p.peekError(t)
	return false
}

// Errors 辅助函数 返回token解析的错误
func (p *Parser) Errors() []string {
	return p.errors
}

// append错误信息
// 注意：词法解析应该要尽量得搜集更多的错误
func (p *Parser) peekError(t token.TokenType) {
	msg := fmt.Sprintf("expected next token to be %s, got %s instead", t, p.peekToken.Type)
	p.errors = append(p.errors, msg)
}

// 没有前缀表达式解析函数错误
func (p *Parser) noPrefixParseFnError(t token.TokenType) {
	msg := fmt.Sprintf("no prefix parse function for %s found", t)
	p.errors = append(p.errors, msg)
}

// ParseProgram 解析Program
func (p *Parser) ParseProgram() *ast.Program {
	program := &ast.Program{}
	program.Statements = []ast.Statement{}

	for !p.currTokenIs(token.EOF) {
		stmt := p.parseStatement()
		if stmt != nil {
			program.Statements = append(program.Statements, stmt)
		}
		p.nextToken()
	}
	return program
}

// 解析语句
func (p *Parser) parseStatement() ast.Statement {
	switch p.currToken.Type {
	case token.LET:
		// 解析let语句
		return p.parseLetStatement()
	case token.RETURN:
		// 解析return语句
		return p.parseReturnStatement()
	default:
		// 解析表达式语句
		return p.parseExpressionStatement()
	}
}

// 解析let语句
func (p *Parser) parseLetStatement() *ast.LetStatement {
	// currToken是let
	stmt := &ast.LetStatement{Token: p.currToken}
	// 如果下一个token不是标识符，返回nil，是的话，会自动nextToken，此时，currToken是标识符
	if !p.expectPeek(token.IDENT) {
		return nil
	}

	// 实例化标识符
	stmt.Name = &ast.Identifier{
		Token: p.currToken,
		Value: p.currToken.Literal,
	}

	// 注意：此时，currToken还是标识符
	// 如果下一个token不是=，返回nil，是的话，会自动nextToken。此时，currToken是=
	if !p.expectPeek(token.ASSIGN) {
		return nil
	}

	// 跳过一个token，这里跳过了=
	p.nextToken()

	// 解析表达式
	stmt.Value = p.parseExpression(LOWEST)

	// 如果下一个token是;，跳到;
	if p.peekTokenIs(token.SEMICOLON) {
		p.nextToken()
	}

	return stmt
}

// 解析return语句
func (p *Parser) parseReturnStatement() *ast.ReturnStatement {
	// currToken是return
	stmt := &ast.ReturnStatement{Token: p.currToken}

	// 跳过一个token，这里跳过了return，return后面是表达式
	p.nextToken()

	// 解析表达式
	stmt.ReturnValue = p.parseExpression(LOWEST)

	// 跳到;
	if p.peekTokenIs(token.SEMICOLON) {
		p.nextToken()
	}

	return stmt
}

// 表达式语句，类似foobar;
func (p *Parser) parseExpressionStatement() *ast.ExpressionStatement {
	// 表达式的第一个token
	stmt := &ast.ExpressionStatement{Token: p.currToken}

	// 解析表达式
	// 这里传了LOWEST最低的优先级，是为了应对中缀表达式的情况
	stmt.Expression = p.parseExpression(LOWEST)

	// 跳到;
	if p.peekTokenIs(token.SEMICOLON) {
		p.nextToken()
	}

	return stmt
}

// 解析表达式
func (p *Parser) parseExpression(precedence int) ast.Expression {
	// 获取前缀表达式的解析函数
	prefix := p.prefixParseFns[p.currToken.Type]
	if prefix == nil {
		p.noPrefixParseFnError(p.currToken.Type)
		return nil
	}

	// 获取前缀表达式的解析函数的返回值
	leftExp := prefix()

	// 如果不是到语句末尾或下一个token的优先级大于当前的优先级
	for !p.peekTokenIs(token.SEMICOLON) && precedence < p.peekPrecedence() {
		// 获取中缀表达式的解析函数
		infix := p.infixParseFns[p.peekToken.Type]
		if infix == nil {
			return leftExp
		}
		// 跳过前缀表达式，此时，当前token是中缀运算符
		p.nextToken()
		// 解析中缀表达式
		leftExp = infix(leftExp)
	}
	// 返回前缀表达式解析函数解析的结果或中缀表达式解析函数解析的结果
	return leftExp
}

// 获取下一个token的优先级，在precedences中匹配不到的话就是最低优先级
func (p *Parser) peekPrecedence() int {
	if p, ok := precedences[p.peekToken.Type]; ok {
		return p
	}
	return LOWEST
}

// 获取当前token的优先级，在precedences中匹配不到的话就是最低优先级
func (p *Parser) currPrecedence() int {
	if p, ok := precedences[p.currToken.Type]; ok {
		return p
	}
	return LOWEST
}

// 解析标识符，直接返回标识符的表达式节点
func (p *Parser) parseIdentifier() ast.Expression {
	return &ast.Identifier{Token: p.currToken, Value: p.currToken.Literal}
}

// 解析整数
// 注意：解析整数时，使用int64存储整数值
func (p *Parser) parseIntegerLiteral() ast.Expression {
	lit := &ast.IntegerLiteral{Token: p.currToken}

	value, err := strconv.ParseInt(p.currToken.Literal, 0, 64)
	if err != nil {
		msg := fmt.Sprintf("could not parse %q as integer", p.currToken.Literal)
		p.errors = append(p.errors, msg)
		return nil
	}

	lit.Value = value

	return lit
}

// 实现Expression接口的方法
func (p *Parser) parseStringLiteral() ast.Expression {
	return &ast.StringLiteral{Token: p.currToken, Value: p.currToken.Literal}
}

// 解析前缀表达式
func (p *Parser) parsePrefixExpression() ast.Expression {
	// 实例化前缀表达式实例
	expression := &ast.PrefixExpression{Token: p.currToken, Operator: p.currToken.Literal}

	// 跳过前缀运算符，此时，当前token是前缀表达式
	// 注意：前缀运算符只有-和!
	p.nextToken()

	// 解析前缀运算符后面的表达式
	expression.Right = p.parseExpression(PREFIX)

	return expression
}

// 解析中缀表达式
// 参数是中缀运算符的左边的表达式
func (p *Parser) parseInfixExpression(left ast.Expression) ast.Expression {
	expression := &ast.InfixExpression{
		Token:    p.currToken,
		Left:     left,
		Operator: p.currToken.Literal,
	}

	// 此时的token是中缀运算符
	// 获取当前的token的优先级
	precedence := p.currPrecedence()
	// 跳过中缀运算符
	p.nextToken()
	// 解析中缀运算符的右边
	expression.Right = p.parseExpression(precedence)

	return expression
}

// 解析bool值
func (p *Parser) parseBoolean() ast.Expression {
	return &ast.Boolean{Token: p.currToken, Value: p.currTokenIs(token.TRUE)}
}

// 解析()
func (p *Parser) parseGroupedExpression() ast.Expression {
	// 跳过(
	p.nextToken()

	// 解析()里面的表达式
	exp := p.parseExpression(LOWEST)

	// 验证有没有)
	if !p.expectPeek(token.RPAREN) {
		return nil
	}

	return exp
}

// 解析if
func (p *Parser) parseIfExpression() ast.Expression {
	// 当前token是if
	expression := &ast.IfExpression{Token: p.currToken}

	// 验证下一个token是不是(
	if !p.expectPeek(token.LPAREN) {
		return nil
	}

	// 跳过(
	p.nextToken()

	// 解析表达式
	expression.Condition = p.parseExpression(LOWEST)

	// 验证)
	if !p.expectPeek(token.RPAREN) {
		return nil
	}

	// 验证{
	if !p.expectPeek(token.LBRACE) {
		return nil
	}

	// 解析块语句
	expression.Consequence = p.parseBlockStatement()

	// 判断下一个token是不是else
	if p.peekTokenIs(token.ELSE) {
		// 跳过else
		p.nextToken()

		// 验证{
		if !p.expectPeek(token.LBRACE) {
			return nil
		}

		// 解析块语句
		expression.Alternative = p.parseBlockStatement()
	}

	return expression
}

// 解析块语句
func (p *Parser) parseBlockStatement() *ast.BlockStatement {
	// 当前token是{
	block := &ast.BlockStatement{Token: p.currToken}
	// 初始化block.Statements
	block.Statements = []ast.Statement{}

	// 跳过{
	p.nextToken()

	// 如果当前token不是}或是结束符，就一直解析语句
	for !p.currTokenIs(token.RBRACE) && !p.currTokenIs(token.EOF) {
		// 解析语句
		stmt := p.parseStatement()
		if stmt != nil {
			// 存储语句
			block.Statements = append(block.Statements, stmt)
		}
		// 跳到下一个语句开头
		p.nextToken()
	}

	return block
}

// 解析函数
func (p *Parser) parseFunctionLiteral() ast.Expression {
	// currToken是fn
	lit := &ast.FunctionLiteral{Token: p.currToken}

	// 验证(
	if !p.expectPeek(token.LPAREN) {
		return nil
	}

	// 解析函数的参数
	lit.Parameters = p.parseFunctionParameters()

	// 验证{
	if !p.expectPeek(token.LBRACE) {
		return nil
	}

	// 解析函数的块语句
	lit.Body = p.parseBlockStatement()

	return lit
}

// 解析函数的参数
func (p *Parser) parseFunctionParameters() []*ast.Identifier {
	// 实例化Identifier切片
	// 注意：当前token是(
	identifiers := []*ast.Identifier{}

	// 判断下一个token是不是)，是的话，跳过)，返回空Identifier切片
	if p.peekTokenIs(token.RPAREN) {
		p.nextToken()
		return identifiers
	}

	// 跳到第一个标识符token
	p.nextToken()

	// 实例化标识符
	ident := &ast.Identifier{Token: p.currToken, Value: p.currToken.Literal}
	// 加入标识符到切片中
	identifiers = append(identifiers, ident)

	// 判断下一个token是不是，是的话就一直解析标识符
	for p.peekTokenIs(token.COMMA) {
		// 跳到,
		p.nextToken()
		// 跳到下一个标识符token
		p.nextToken()
		// 实例化标识符
		ident := &ast.Identifier{Token: p.currToken, Value: p.currToken.Literal}
		// 加入标识符到切片中
		identifiers = append(identifiers, ident)
	}

	// 验证)
	if !p.expectPeek(token.RPAREN) {
		return nil
	}

	return identifiers
}

// 解析调用表达式
func (p *Parser) parseCallExpression(function ast.Expression) ast.Expression {
	// 实例化表达式
	exp := &ast.CallExpression{Token: p.currToken, Function: function}
	// 解析调用表达式的参数
	// 注意：调用表达式的参数不只有标识符，还可以有函数，整数，前缀表达式和中缀表达式
	exp.Arguments = p.parseExpressionList(token.RPAREN)

	return exp
}

// 解析表达式列表，可以是参数列表，数组和哈希表
func (p *Parser) parseExpressionList(end token.TokenType) []ast.Expression {
	list := []ast.Expression{}

	// 如果下一个token是)，跳过)，返回空切片
	if p.peekTokenIs(end) {
		p.nextToken()
		return list
	}

	// 跳过)
	p.nextToken()
	// 解析第一个参数，并加入切片
	list = append(list, p.parseExpression(LOWEST))

	// 如果下一个token是,，就一直解析参数
	for p.peekTokenIs(token.COMMA) {
		// 跳到,
		p.nextToken()
		// 跳到下一个表达式的首个token
		p.nextToken()
		// 解析表达式，并加入切片
		list = append(list, p.parseExpression(LOWEST))
	}

	// 验证)
	if !p.expectPeek(end) {
		return nil
	}

	return list
}

// 解析数组
func (p *Parser) parseArrayLiteral() ast.Expression {
	array := &ast.ArrayLiteral{Token: p.currToken}

	// 解析数组元素
	array.Elements = p.parseExpressionList(token.RBRACKET)

	return array
}

// 解析index表达式
func (p *Parser) parseIndexExpression(left ast.Expression) ast.Expression {
	exp := &ast.IndexExpression{Token: p.currToken, Left: left}

	p.nextToken()
	exp.Index = p.parseExpression(LOWEST)

	if !p.expectPeek(token.RBRACKET) {
		return nil
	}

	return exp
}

func (p *Parser) parseHashLiteral() ast.Expression {
	hash := &ast.HashLiteral{Token: p.currToken}
	hash.Pairs = make(map[ast.Expression]ast.Expression)

	for !p.peekTokenIs(token.RBRACE) {
		p.nextToken()
		key := p.parseExpression(LOWEST)

		if !p.expectPeek(token.COLON) {
			return nil
		}

		p.nextToken()

		value := p.parseExpression(LOWEST)
		hash.Pairs[key] = value

		if !p.peekTokenIs(token.RBRACE) && !p.expectPeek(token.COMMA) {
			return nil
		}
	}

	if !p.expectPeek(token.RBRACE) {
		return nil
	}

	return hash
}

// 注册前缀表达式
// 注册identifier，int，bool，-，!，if，fn
func (p *Parser) registerPrefix(tokenType token.TokenType, fn prefixParseFn) {
	p.prefixParseFns[tokenType] = fn
}

// 注册中缀表达式
func (p *Parser) registerInfix(tokenType token.TokenType, fn infixParseFn) {
	p.infixParseFns[tokenType] = fn
}
